package ipad.asia.controller;
import com.alibaba.fastjson.JSON;


import com.zengtengpeng.annotation.Lock;
import ipad.asia.dao.SecKillOrderDao;
import ipad.asia.dao.SecKillProductDao;
import ipad.asia.entity.Product;
import ipad.asia.entity.SeckillOrder;
import ipad.asia.entity.SeckillProduct;
import ipad.asia.utils.MyTime;
import org.junit.jupiter.api.Test;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.persistence.LockModeType;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@RestController
@Transactional
public class SecKillController {
//--add-opens java.base/java.lang=ALL-UNNAMED
    private static String product1Count = "product1Count";//商品1的数量key
    private static String lockKey = "redisKey";//分布式锁的key
//    @Autowired
//    private RedissonClient redissonClient;
    @Autowired
    private SecKillProductDao secKillProductDao;
    @Autowired
    private SecKillOrderDao secKillOrderDao;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
   private MyTime myTime;
//    @RequestMapping("/secKill/go")
    @RequestMapping("/secKill/jvm")
    @Transactional
    public int secKill(@RequestParam(value = "productId") int productId,
                        @RequestParam(value = "consumerId") int consumerId){
        /**
         * redis做法, 基于单机的JVM同步锁
         */
            synchronized (this){
            String json = JSON.toJSONString(redisTemplate.opsForValue().get("secKill:" + productId));
            SeckillProduct seckillProduct = JSON.parseObject(json, SeckillProduct.class);
                System.out.println(seckillProduct.getNumber());
            if (seckillProduct.getNumber() == 0) {
                System.out.println("库存不足");
                return 1;
            } else {
                if (redisTemplate.opsForValue().get(productId + "secKillUser" + consumerId) != null) {
                    System.out.println("不能购买同一件");
                    return 2;
                } else {
                    //库存减一，更新库存
                    int result = seckillProduct.getNumber() - 1;
                    seckillProduct.setNumber(result);
                    System.out.println("result:" + result);
                    redisTemplate.opsForValue().set("secKill:" + productId, seckillProduct);
                    redisTemplate.opsForValue().set(productId + "secKillUser" + consumerId, seckillProduct.getProductId());
//                    redisTemplate.opsForValue().set("secKillUser:" + productId + "secKillUser" + consumerId, seckillProduct.getProductId());
                    return 3;
                }
                }
            }
    }


    @RequestMapping("/secKill/go")
    @Lock(keys = "#productId",keyConstant = "secKillProduct")
    public int secKillDCS(@RequestParam(value = "productId") int productId,
                       @RequestParam(value = "consumerId") int consumerId){
        /**
         * redis做法, 基于分布式redis集群redission分布式锁
         * 采用gitee中国人的com.zengtengpeng，使用不错
         * 已通过压测
         * 文档地址：https://gitee.com/ztp/redisson-spring-boot-starter
         * @作者：冯东旺
         */
            String json = JSON.toJSONString(redisTemplate.opsForValue().get("secKill:" + productId));
            SeckillProduct seckillProduct = JSON.parseObject(json, SeckillProduct.class);
            if (seckillProduct.getNumber() == 0) {
                System.out.println("库存不足");
                return 1;
            } else {
                if (redisTemplate.opsForValue().get(productId + "secKillUser" + consumerId) != null) {
                    System.out.println("不能购买同一件");
                    return 2;
                } else {
                    //库存减一，更新库存
                    int result = seckillProduct.getNumber() - 1;
                    seckillProduct.setNumber(result);
                    System.out.println("减一后的库存result:" + result);
                    redisTemplate.opsForValue().set("secKill:" + productId, seckillProduct);
                    redisTemplate.opsForValue().set(productId + "secKillUser" + consumerId, seckillProduct.getProductId());
//                    redisTemplate.opsForValue().set("secKillUser:" + productId + "secKillUser" + consumerId, seckillProduct.getProductId());
                    return 3;
                }
            }

        }

//                SeckillProduct seckillProduct = secKillProductDao.findByProductId(productId);
//                int count=seckillProduct.getNumber();
//                SeckillOrder seckillOrder = new SeckillOrder();
//                if (secKillProductDao.findByProductId(productId).getNumber() == 0) {
//                    System.out.println("库存不足");
//                } else {
//                    if (secKillOrderDao.findByConsumerIdAndProductId(consumerId, productId).size() > 0) {
//                        System.out.println("每人只可以抢购一件");
//                    } else {
//                        count--;
//                        secKillProductDao.update(count,productId);
//                        seckillOrder.setConsumerId(consumerId).setProductId(productId);
//                        secKillOrderDao.save(seckillOrder);
//                    }
//                }





    @GetMapping("/secKill/list")
    public List<SeckillProduct> products(){
        return secKillProductDao.findAll();
    }


    @RequestMapping("/secKill/productSave")
    public void addSecKill(@RequestParam(value = "productId",required = false) Integer productId,
                           @RequestParam(value = "price",required = false)Float price,
                           @RequestParam(value = "number",required = false)Integer number,
                           @RequestParam(value = "start",required = false) String start,
                           @RequestParam(value = "end",required = false) String end){
        SeckillProduct seckillProduct = new SeckillProduct();
        seckillProduct.setNumber(number).setProductId(productId).setDateStart(start).
                setDateEnd(end).setPrice(price).setNumberStart(number);
        secKillProductDao.save(seckillProduct);
        SeckillProduct secKillProduct1=secKillProductDao.findByProductId(productId);
        redisTemplate.opsForValue().set("secKill:"+productId,secKillProduct1);
        redisTemplate.opsForValue().set("startSecKill:"+productId,secKillProduct1);
    }

    @Transactional
    @RequestMapping("/secKill/delete")
    public void deleteSecKill(@RequestParam(value = "productId",required = false) Integer productId){
        secKillProductDao.deleteByProductId(productId);
        redisTemplate.delete("startSecKill:"+productId);
        redisTemplate.delete("secKill:"+productId);
    }

    @Transactional
    @RequestMapping("/secKill/deleteNoPay")
    public void deleteNoPay(@RequestParam(value = "productId",required = false) Integer productId,
                            @RequestParam(value = "consumerId",required = false)Integer consumerId){
        String json= JSON.toJSONString(redisTemplate.opsForValue().get("secKill:"+productId));
        SeckillProduct seckillProduct=JSON.parseObject(json,SeckillProduct.class);
        int result=seckillProduct.getNumber()+1;
        seckillProduct.setNumber(result);
        redisTemplate.opsForValue().set("secKill:"+productId,seckillProduct);
        redisTemplate.delete(productId+"secKillUser"+consumerId);
    }

    @RequestMapping("/secKill/getById")
    public SeckillProduct getById(@RequestParam(value = "productId",required = false) Integer productId){
        String json= JSON.toJSONString(redisTemplate.opsForValue().get("secKill:"+productId));
        SeckillProduct seckillProduct=JSON.parseObject(json,SeckillProduct.class);
        return seckillProduct;
    }

    @RequestMapping("/secKill/StartById")
    public SeckillProduct StartById(@RequestParam(value = "productId",required = false) Integer productId){
        String json= JSON.toJSONString(redisTemplate.opsForValue().get("startSecKill:"+productId));
        SeckillProduct seckillProduct=JSON.parseObject(json,SeckillProduct.class);
        return seckillProduct;
    }

//    @Test
//    @RequestMapping("/test")
//    public int test(@RequestParam(value = "productId") int productId,
//                    @RequestParam(value = "consumerId") int consumerId){
//        String json = JSON.toJSONString(redisTemplate.opsForValue().get("secKill:" + productId));
//        SeckillProduct seckillProduct = JSON.parseObject(json, SeckillProduct.class);
//        System.out.println(seckillProduct);
//        System.out.println(seckillProduct.getNumber());
//        SeckillProduct seckillProduct = (SeckillProduct) redisTemplate.opsForValue().get("secKill:" + productId);
//        System.out.println(seckillProduct);
//        System.out.println(redisTemplate.opsForValue().get("secKill:" + productId));
//        RLock lock = redissonClient.getLock(lockKey);
//        try {
//            lock.lock(5, TimeUnit.SECONDS);
//            if (seckillProduct.getNumber() == 0) {
//                System.out.println("库存不足");
//                return 1;
//            } else {
//                if (redisTemplate.opsForValue().get(productId + "secKillUser" + consumerId) != null) {
//                    System.out.println("不能购买同一件");
//                    return 2;
//                } else {
//                    //库存减一，更新库存
//                    int result = seckillProduct.getNumber() - 1;
//                    seckillProduct.setNumber(result);
//                    System.out.println("result:" + result);
//                    redisTemplate.opsForValue().set("secKill:" + productId, JSON.toJSONString(seckillProduct));
////                    redisTemplate.opsForValue().set(productId + "secKillUser" + consumerId, seckillProduct.getProductId());
//                    redisTemplate.opsForValue().set("secKillUser:" + productId + "secKillUser" + consumerId, JSON.toJSONString(seckillProduct.getProductId()));
//                    return 3;
//                }
//            }
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }finally {
//            lock.unlock();
//        }
//        return 4;
//    }


}
